iT邦幫忙

2023 iThome 鐵人賽

DAY 4
1
Modern Web

起步Go!Let's Go!系列 第 4

[ Day 04 ] Go 的資料型態及運用

  • 分享至 

  • xImage
  •  

Go 是一種靜態強型別的程式語言,所以所有資料在編譯時都需要賦予一種資料型態,且不允許不同資料型別之間的隱式轉換。也因如此在編譯的過程中若資料型別不匹配或有問題,編譯器將立即產生錯誤消息。
接下來就來認識一下有哪些資料型態。

資料型態

資料型態是什麼呢?
資料為程式中基本的運作單位,而資料會有不同的型態,故稱為資料型態。
常見的資料型態有哪些呢?

1. 整數( int )

包含 0 和正負整數。
例如:-22,4324,0

Go 在整數提供多種型態:

int8, uint8
int16, uint16
int32, uint32
int64, uint64
int , uint (大部分情況視為 int64, uint64)

另外 uint 只能是正數(不能帶符號),int 可以有負數(可以帶符號)
至於為甚麼都是 8 的倍數,因為電腦會以 8 個 bits 做操作,所以又稱 8 bits 為 1 byte (1個位元組)。

2. 浮點數( float )

用於表示小數和實數數值,包含 0 和正負小數,例如:3.1415。

在 Go 上宣告浮點數是 IEEE754 來處理,簡單來說,就是將一串浮點數拆成科學記號來表示,而 Go 有兩種小數的宣告方法: float32, float64

float64 花了兩倍空間去存放,所以會比 float32 來的精準,通常會稱 float64 為雙精度浮點數。

3. 字元 rune

在了解字串前,先了解字元,字元就是"表達單一字符",每個字元對應到的都會是一個整數,所以字元背後實際上存放的是整數。
在 Go,是以 UTF8 作為字元的轉法,舉例來說:'a'(這裡會使用單引號使用雙引號會變成字串型態),'a' 對應到的就是 97。

package main
import "fmt"
func main(){
    var a rune = '你'
    var b rune = '好'
    var c rune = '!'
    fmt.Println(a)
    fmt.Println(b)
    fmt.Println(c)
}

執行結果:
20320
22909
33

為甚麼要有形態?

主要是為了工程師方便做事,在沒有型態的情況下,根本不知道要用「你」還是要用 20320,因為這兩個在 Go 中都長的一樣。所以引入rune資料型態,確保工程師可以以一種統一的方式處理各種字符,而不必擔心字符的具體表示方式或大小。

那又為什麼執行結果會是這樣呢?

因為 rune 就是 intr32,通過 fmt.Println 就會把它當作數字來處理,如果我們要印出的是要純文字,就需要用到 fmt.PrintfPrintf 指的就是 print + formatformat 決定要以甚麼形式印出。

package main
import "fmt"
func main(){
    var a rune = '你'
    var b rune = '好'
    var c rune = '!'
    fmt.Printf("%c", a)
    fmt.Printf("%c", b)
    fmt.Printf("%c", c)
}

執行結果:
你好!

也可以用 %c%c,Go 會依序對應 , 後面的變數。

package main
import "fmt"
func main(){
    var a rune = '你'
    var b rune = '好'
    var c rune = '!'
    fmt.Printf("%c%c%c", a, b, c)
}

執行結果:
你好!

除了 %c,常用的還有 %d, %f, %s
%c : c 是指 character 以字元印出。
%d : d 是指 decimal 以十進位印出
%e : e 是指 exponent 以科學計號方式印出
%f : f 是指 float 以浮點數印出
%s : s 是指 string 以字串印出
%% : 是用來印出 % 不然 Printf 會有 bug

解析單引號''

當'你'加上單引號後,Go 就會直接把這個字變成 20320,做個小實驗:

package main
import "fmt"
func main(){
    var a rune = '你' - 20000
    fmt.Printf("%d", a)
}

執行結果:
320

在 Go,rune 會被視為 int32,所以'你'會直接被視為20320,那'你' - 20000 就會變成 20320-20000
fmt.Printf("%d", a) 則是會被視為 fmt.Printf("%d", 320)

2. 字串 string

知道字元,那就可以來認識字串了。
根據上面的介紹,字元不過就是一串數字,那字串就是一串字元,那先講解到這裡,我們先知道怎麼使用就行了,原理的先擺到一邊,先來個例子:

package main
import "fmt"
func main(){
    var release string = "你好!Golang"
    release2  := "Hello!world"
    fmt.Println(release)
    fmt.Println(release2)
}

執行結果:
你好!Golang
Hello!world

3. 布林值

表達正確 ( true ) 和錯誤 ( false ),通常用於條件測試和邏輯運算。
例如:

if condition {
    // 當 condition 為 ture 會執行這段
} else {
    // 當 condition 為 false 會執行這段
}

有關 condition 條件式後面的章節會再細講。

4. 還有哪些資料型態

除了以上的資料型態以外還有多種資料型態,如下:

  • 切片類型(Slice Type):用於動態數組,是對數組的引用。
  • 數組類型(Array Type):固定大小的數組。
  • 映射類型(Map Type):鍵-值對的集合。
  • 結構體類型(Struct Type):用於自定義數據結構。
  • 函數類型(Function Type):表示函數的類型,可用於函數變數。
  • 通道類型(Channel Type):用於在goroutines之間通信的類型。

運用

上面介紹了多種的資料型態,接著我們來看看要使用這些資料型態。

1. 整數運算

加減乘除

package maing
import "fmt"
func main(){
    n := 10
    m := 20
    fmt.Println(n + m)
    fmt.Println(n - m)
    fmt.Println(n * m)
    fmt.Println(m / n)
    fmt.Println(n / m)
}

執行結果
30
-10
200
2
0

大部分的語言,整數對整數算出來都會是整數,即使是除法,除不盡的狀況也會是整數。
所以當 n / m 也就是 10/20,在數學計算中會是 0.5,但在電腦科學中會直接當作 0
如果有負數,比如 -3/2 = -1.5 那會變 -2 或是 -1 呢?只要把小數去掉即可,所以會是 -1。舉例來說:

package main
import "fmt"
func main(){
    fmt.Println(-3/2)
}

執行結果
-1

取餘數

在 Go 中,要怎麼取餘數呢?我們會使用 % 來表達要取餘數。

package main
import "fmt"
func main(){
    fmt.Println(30 % 2)
    fmt.Println(28 % 3)fmt.Println(23 % 5)
}

執行結果
0
1
3

有負數的情況如下:

package main
import "fmt"
func main(){
    fmt.Println(23 % 6)
    fmt.Println(-23 % 6)
    fmt.Println(23 % -6)
    fmt.Println(-23 % -6)
}

執行結果
5
-5
5
-5

2. 浮點數的運算

浮點數的運算與整數的運算基本都差不多,但要注意一點,浮點數可以和直接整數(單純數字)做運算,但不能和整數變數(英文)做運算。
在 Go 中,會將純數字直接轉成浮點數

package main
import "fmt"
func main(){
    m := 2
    m = m / 2
    fmt.Println(m)
}

執行結果
1.25

package main
import "fmt"
func main(){
    m := 2.5
    n := 2
    m = m / n
    fmt.Println(m)
}

執行結果
invalid operation: m / n (mismatched types float64 and int) (exit status 1)

在這邊是沒辦法這樣去做運算的,但是又真的要這樣去做運算,那就轉換型別!
轉換型別就是把把浮點數轉成整數,或是把整數轉成浮點數。

3. 型別轉換

如果想要把 int 轉成 float 64 那只要在要轉換的變數外加上 flaot 64() 就可以了。

package main
import "fmt"
func main(){
    m := 2.5
    n := 2
    m = m / float64(n)
    fmt.Println(m)
}

執行結果
1.25

這樣被套上的 float64() 的變數(n),就會以 float64 的型態去與 m 做計算,要注意 n 依舊是 int,只有被套上 float64() 才會變成 float64
簡單來說,在宣告變數後,該變數就只能是一開始宣告時的型態。

package main
import "fmt"
func main(){
    n := 2
    n = float64(n)
    fmt.Println(n)
}

執行結果
cannot use float64(n) (value of type float64) as int value in assignment (exit status 1)

4. 字串加法

字串的運算只有加法而已,如下:

package main
import "fmt"
func main(){
    str1 := "How are you?"
    str2 := "I'm fine!"
    fmt.Println(str1 + str2)
}

執行結果:
How are you?I'm fine!

但是如果在這中間加了數字進去會發生甚麼事呢?

package main
import "fmt"
func main(){
    name := "Tom is"
    yearsOld:= "years old"
    fmt.Println(name + 10 + yearsOld)
}

執行結果:
invalid operation: name + 10 (mismatched types string and untyped int) (exit status 1)

直接報錯,因為 10 不是字串所以不能直接加,這是一個不錯的設計,為甚麼這樣說?
因為在 JS,在進行加法時,有時會誤把數字當作字串去做相加,所以並不好知道這個變數是數字還是字串。而 PythonGo 則會把數字跟字串相加,視為一種錯誤。
簡單來說,在 GO 中:

運算 是否可執行
String + Srting OK
Int + Int OK
String + Int error
那我們要怎麼解決這個問題呢?

數字轉成字串

如果只是要印出來的話,可以用 Printf 來印出。

方法一: Printf

package main
import "fmt"
func main(){
    name := "Tom is"
    yearsOld:= "years old"
    fmt.Printf("%s%d%s",name, 10, yearsOld)
}

執行結果:
Tom is10years old

方法二: Print

package main
import "fmt"
func main(){
    name := "Tom is"
    yearsOld:= "years old"
    fmt.Print(name, 10, yearsOld)
}

執行結果:
Tom is10years old

fmt.Print(name, 10, yearsOld) 這段可以被視為:

fmt.Print(name)
fmt.Print(" ")
fmt.Print(10)
fmt.Print(" ")
fmt.Print(yearsOld)

方法三: Sprintf()

package main
import "fmt"
func main(){
    name := "Tom is"
    yearsOld := "years old"
    result := fmt.Sprintf("%s%d%s", name, 10, yearsOld)
    fmt.Printf(result)
}

今天介紹了 Go 的資料型態以及怎麼使用它,明天我們將學習 Go 的基本運算符號。

參考資料:

  1. Golang 資料、資料型態與變數 By 彭彭
  2. 更多的相關類型可以到 Golang 官網查詢: https://go.dev/ref/spec#Numeric_types

上一篇
[ Day 03 ] 你的第一支 Go 程式
下一篇
[Day 05 ] Go 運算符號:舞動程式碼的魔杖
系列文
起步Go!Let's Go!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言